package cn.edu.lzzy.mypractices.service;

import cn.edu.lzzy.mypractices.constant.Messages;
import cn.edu.lzzy.mypractices.entity.Chapter;
import cn.edu.lzzy.mypractices.entity.Course;
import cn.edu.lzzy.mypractices.repository.ChapterRepository;
import cn.edu.lzzy.mypractices.util.AuthUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.awt.print.Pageable;
import java.util.List;
import java.util.UUID;

@Service
public class ChapterServiceImpl implements ChapterService {
    public ChapterRepository repository;

    public ChapterServiceImpl(ChapterRepository repository) {
        this.repository = repository;
    }

    // 通过课程获取所有章节
    @Cacheable(value = "chapters", key = "#course.id.toString()")
    @Override
    public List<Chapter> getByCourse(Course course) {
        return repository.findAllByCourseOrderByUpdateTimeDesc(course);
    }

    // 通过课程获取所有章节 but 分页
    @Cacheable(value = "pagedChapters", key = "#course.id.toString() + '_' + #page + '_' + #size")
    @Override
    public List<Chapter> getByCourse(Course course, int page, int size) {
        return repository.findAllByCourseOrderByUpdateTimeDesc(course, PageRequest.of(page, size));
    }

    // 通过课程ID获取所有章节
    @Cacheable(value = "chapters", key = "#course_id.toString()")
    @Override
    public List<Chapter> getByCourse(UUID course_id) {
        return repository.findAllByCourseIdOrderByUpdateTimeDesc(course_id);
    }

    // 通过课程ID获取所有章节 but 分页
    @Cacheable(value = "pagedChapters", key = "#course_id.toString() + '_' + #page + '_' + #size")
    @Override
    public List<Chapter> getByCourse(UUID course_id, int page, int size) {
        return repository.findAllByCourseIdOrderByUpdateTimeDesc(course_id, PageRequest.of(page, size));
    }

    @Cacheable(value = "chapterCount", key = "#id.id.toString()")
    @Override
    public int count(Course id) {
        return repository.countAllByCourse(id);
    }

    @Cacheable(value = "chapterCount", key = "#id.toString()")
    @Override
    public int count(UUID id) {
        return repository.countAllByCourseId(id);
    }

    // 通过章节ID获取章节
    @Cacheable(value = "chapterById", key = "#id.toString()")
    @Override
    public Chapter getByChapterId(UUID id) {
        return repository.findById(id).orElse(null);
    }

    // 缓存
    @Caching(put = {
            @CachePut(value = "chapterById", key = "#chapter.id.toString()")
    }, evict = {
            @CacheEvict(value = "chapters", key = "#chapter.course.id.toString()"),
            @CacheEvict(value = "pagedChapters", allEntries = true),
            @CacheEvict(value = "chapterCount", allEntries = true)
    })
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Chapter add(Chapter chapter) {
        return repository.save(chapter);
    }

    @Caching(put = {
            @CachePut(value = "chapterById", key = "#chapter.id.toString()")
    }, evict = {
            @CacheEvict(value = "chapters", key = "#chapter.course.id.toString()"),
            @CacheEvict(value = "pagedChapters", allEntries = true),
            @CacheEvict(value = "chapterCount", allEntries = true)
    })
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Chapter update(Chapter chapter, String token) {
        return repository.save(chapter);
    }

    // 移除
    @Caching(evict = {
            @CacheEvict(value = "chapterById", key = "#id.toString()"),
            @CacheEvict(value = "chapters", allEntries = true),
            @CacheEvict(value = "pagedChapters", allEntries = true),
            @CacheEvict(value = "chapterCount", allEntries = true)
    })
    @Override
    public Messages remove(UUID id, String token) {
        Chapter chapter = repository.findById(id).orElse(null);
        if (chapter == null) {
            return Messages.WRONG_ID;
        }

        UUID teacherId = chapter.course.getTeacher().getId();
        if (AuthUtils.invalid(teacherId, token)) {
            return Messages.NO_PERMISSION;
        }

        repository.delete(chapter);
        return Messages.SUCCESS;
    }
}
